import { Graph, Cell, Node, Edge, Model, Shape, CellView, } from '@antv/x6'
import { Stencil } from '@antv/x6-plugin-stencil'
import { Snapline } from '@antv/x6-plugin-snapline'
import { Transform } from '@antv/x6-plugin-transform'
import { ElMessage } from 'element-plus'
import { cellHighlightShow, initOnLine, initRegisterNode } from './graphTing'
import { Keyboard } from '@antv/x6-plugin-keyboard'
import { History } from '@antv/x6-plugin-history'
interface graphGridOptions {
    visible: boolean,
    type: string,
    size: number
}

/**
 * @description graph interface
 */
interface InitGraphOptions {
    containerId?: string
    stencilId?: string
    width?: number
    height?: number
    backgroundColor?: string
    grid?: graphGridOptions
    autosize: boolean
}

/**
 * @description Antx6 
 */
class GraphManager {
    private graph: Graph | null = null
    private optionValues: InitGraphOptions

    constructor(options: InitGraphOptions) {
        const {
            containerId = 'graph-container',
            width = 800,
            height = 600,
            backgroundColor = '#F2F7FA',
            grid = { visible: true, type: 'mesh', size: 10 },
            autosize,
            ...otherOptions
        } = options
        this.optionValues = options
        const container = document.getElementById(containerId)
        if (!container) {
            ElMessage.warning('画布初始化节点未找到')
            return
        }
     
        this.graph = new Graph({
            container,
            width: autosize ? undefined : width,
            height: autosize ? undefined : height,
            autoResize: autosize,
            background: { color: backgroundColor },
            ...otherOptions,
            grid: {
                visible: grid.visible,
                size: 10,
                type: grid.type,
                args: {
                    color: '#a0a0a0', // 网点颜色
                    thickness: 1, // 网点大小
                },
            },
            connecting: {
                router: 'manhattan',
                connector: {
                    name: 'rounded',
                    args: {
                        radius: 8,
                    },
                },
                anchor: 'center',
                connectionPoint: 'anchor',
                allowBlank: false,
                snap: {
                    radius: 20,
                },
                createEdge() {
                    return new Shape.Edge({
                        attrs: {
                            line: {
                                stroke: '#A2B1C3',
                                strokeWidth: 2,
                                targetMarker: {
                                    name: 'block',
                                    width: 12,
                                    height: 8,
                                },
                            },
                        },
                        zIndex: 0,
                    })
                },
                validateConnection({ targetMagnet }) {
                    return !!targetMagnet
                },
            },
            // 设置子元素不可脱离父元素
            translating: {
                restrict(view: CellView<Cell<Cell.Properties>, CellView.Options> | null) {
                    const cell = view?.cell
                    if (cell?.isNode()) {
                        const parent = cell.getParent()
                        if (parent) {
                            return parent.getBBox()
                        }
                    }

                    return null
                },
            },
        })
        this.graph.use(
            new Transform({
                resizing: true,
                rotating: true,
            }),
        ).use(new Snapline())
            .use(new History())
            .use(new Keyboard({
                enabled: true,
                global: true,
            }))
        cellHighlightShow(this.graph)
    }

    /**E
     * @description 启用编辑器
     */
    initEditGraph() {
        this.graph?.use(new Stencil())
        const stencil = new Stencil({
            title: '流程图组件',
            target: this.graph as Graph,
            stencilGraphWidth: 200,
            stencilGraphHeight: 180,
            collapsable: true,
            groups: [
                {
                    title: '基础流程图',
                    name: 'group1',
                },
                {
                    title: '系统设计图',
                    name: 'group2',
                },
            ],
            layoutOptions: {
                columns: 2,
                columnWidth: 80,
                rowHeight: 55,
            },
        })
        document.getElementById(this.optionValues.stencilId as string)!.appendChild(stencil.container)
        initRegisterNode()
        initOnLine(this.graph as Graph)
        return stencil
    }


    /**
     * @description get instance
     */
    getGraphInstance() {
        return this.graph
    }

    /**
     * @description getGraph
     */
    getGraph(data: Model.FromJSONData) {
        return this.graph?.fromJSON(data)
    }
    /**
     * @description addNode
     */
    addNode(config: Node.Metadata) {
        return this.graph?.addNode(config)
    }

    /**
     * @description addEdge 
     */
    addEdge(config: Edge.Metadata) {
        return this.graph?.addEdge(config)
    }

    /**
     * @description addCells
     */
    addCells(cells: Cell[]) {
        this.graph?.addCell(cells)
    }

    /**
     * @description 监听
     */
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    on(event: string, callback: (...args: any[]) => void) {
        this.graph?.on(event, callback)
    }

    /**
     * @description setZoom 缩放
     * @param factor Zoom level (1 = 100%)
     */
    setZoom(factor: number) {
        this.graph?.zoom(factor)
    }

    /**
     * @description centerContent 居中
     */
    centerContent() {
        this.graph?.centerContent()
    }

    /**
     * @description clear 清除
     */
    clear() {
        this.graph?.clearCells()
    }

    /**
     * @description destroy 销毁
     */
    destroy() {
        this.graph?.dispose()
    }
}
export { GraphManager }
export type { Graph as GraphType, Node, Edge }
